const add = (x, y) => x + y;
const square = z => z * z;

/**
 * 解释函数组合Compose - 洋葱模型
 * @param {*} x 
 * @param {*} y 
 */
// const fn = (x, y) => square(add(x, y));

// const compose = (fn1, fn2) => (...args) => fn2(fn1(...args));

// const compose = (...[first, ...other]) => (...args) => {
//     let ret = first(...args);
//     other.forEach(fn => {
//         ret = fn(ret); 
//     })
//     return ret;
// }
// const val1 = compose(add, square, square)(1,2);
// const val2 = compose(add, square)(1,2);
// console.log(val1, val2); // 81, 9


function compose(middlewares) {
    return function (ctx) {
        return dispatch(0);
        function dispatch(i) {
            let fn = middlewares[i];
            if(!fn) {
                return Promise.resolve();
            }
            return Promise.resolve(fn(ctx, function next() {
                return dispatch(i + 1);
            }))
        }
    }
}


async function fn1(next) {
    console.log("fn1...");
    await next();
    console.log("end fn1");
}

async function fn2(next) {
    console.log("fn2...");
    await next();
    console.log("end fn2");
}

async function fn3(next) {
    console.log("fn3...");
    await next();
    console.log("end fn3");
}

const middlewares = [fn1, fn2, fn3];
const finalFn = compose(middlewares);
finalFn();
